﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GestionePolveriLib.BL;
using FluentValidation;
using FluentValidation.Results;
using GestionePolveriLib.Facades;

namespace GestionePolveriLib.Validations
{
    public class MovimentoValidator : AbstractValidator<Movimento>
    {
        private double m_quantita = 0;

        public MovimentoValidator(double quantita) : this()
        {
            m_quantita = quantita;
        }

        public MovimentoValidator()
        {
            //RuleFor(m => m.Turno).NotNull().WithMessage("Seleziona un Turno 1!");
            RuleFor(m => m.Turno.Id).GreaterThan((short)-1).WithMessage("Seleziona un Turno !");

            //RuleFor(m => m.Impianto).NotEmpty().WithMessage("Seleziona un Impianto 1!");
            RuleFor(m => m.IDImpianto).GreaterThan(-1).WithMessage("Seleziona un Impianto !");

            RuleFor(m => m.IDPolvere).NotEmpty().WithMessage("Seleziona un Codice Polvere !");

            RuleFor(m => m.IDLotto).NotEmpty().WithMessage("Attenzione!... e' necessario selezionare un lotto !");

            //RuleFor(m => m.Lotto).Must(CheckLotto).WithMessage("Il Lotto risulta Non Conforme e Bloccato.\nVerificare che l'impianto utilizzato sia un impianto fittizio!");

            RuleFor(m => m.NumScatole).GreaterThanOrEqualTo(0).WithMessage("Numero scatole non valido. Inserire un valore maggiore di zero");

            //RuleFor(m => m.Lotto).NotNull().WithMessage("Attenzione!... e' necessario selezionare un lotto !");

            /*
             * se il lotto è NC in stato BLOCCATO, non si può scaricare dagli impianti reali, ma solo da quelli fittizi; 
             * non deve essere prevista in tale situazione la prenotazione della polvere.
             */
            Custom(m => {
                return (CheckLottoBloccatoAndImpiantoFittizio(m)
                        ? new ValidationFailure("Lotto", "Il Lotto risulta Non Conforme e Bloccato.\nVerificare che l'impianto utilizzato sia un impianto fittizio!")
                        : null
                        );
            });

            /*
             * se il lotto è conforme o NC in stato ACCETTATO, può essere scaricato su qualunque impianto; 
             * in presenza di prenotazione deve essere:
             * Quantità disponibile dopo lo scarico ≥ Quantità prenotata
             */
            Custom(m =>
            {
                return (CheckLottoConformeONCAccettato(m)
                        ? null
                        : new ValidationFailure("Lotto", "Attenzione: La quantità disponibile dopo lo scarico è minore della quantità prenotata !")
                        );
            });
        }

        private bool CheckLottoBloccatoAndImpiantoFittizio(Movimento movimento)
        {
            bool retValue = false;

            if ((movimento.Lotto != null) && (movimento.Lotto.LottoNCInfo != null) && (movimento.Lotto.LottoNCInfo.IsLottoBloccato.GetValueOrDefault()))
            {
                Impianto imp = (Impianto)movimento.ImpiantoInternal;

                if (!imp.Fittizio)
                {
                    retValue = true;
                }
            }

            return retValue;
        }

        private bool CheckLottoConformeONCAccettato(Movimento movimento)
        {
            bool retValue = false;

            try
            {               
                if ((movimento.LottoNCInfo != null) && (movimento.LottoNCInfo.IsLottoBloccato.GetValueOrDefault()))
                {
                    retValue = true;
                }
                else
                {
                    //if (((movimento.Lotto != null) && (movimento.Lotto.LottoNCInfo == null)) ||
                    //    ((movimento.Lotto != null) && (movimento.Lotto.LottoNCInfo.IsLottoNC)))
                    //{
                    // se c'è una prenotazione:
                    // Quantità disponibile dopo lo scarico ≥ Quantità prenotata
                    double m_quantDaScaricare = movimento.Quantita;

                    PolvereFacade pf = new PolvereFacade();
                    Polvere m_polvere = pf.Get(movimento.Lotto.IDPolvere);

                    LottoFacade lf = new LottoFacade();
                    m_polvere.Giacenza = lf.GetGiacenza(m_polvere.ID) + m_quantita;

                    PrenotazioniFacade prf = new PrenotazioniFacade();
                    double m_quantitaPrenotata = prf.GetQuantitaImpegnata(movimento.Lotto.IDPolvere);
                    m_polvere.QuantitaImpegnata = m_quantitaPrenotata;

                    LottoNCFacade lncf = new LottoNCFacade();
                    m_polvere.QuantitaNCBlocked = lncf.GetQuantitaBlocked(m_polvere.ID);

                    double m_quantitaDopoLoScarico = (m_polvere.QuantitaDisponibile.HasValue ? m_polvere.QuantitaDisponibile.Value : 0) - m_quantDaScaricare;

                    //if ((m_quantitaDopoLoScarico > 0) &&
                    //    (m_quantitaDopoLoScarico > m_quantitaPrenotata))
                    if (m_quantitaDopoLoScarico >= 0)
                    {
                        retValue = true;
                    }
                    //}
                }
            }
            catch
            {
                retValue = false;
            }

            return retValue;
        }
    }
}
